package com.lianqi.emcpframework.shiro.cas.realm;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.pac4j.core.profile.CommonProfile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;

import io.buji.pac4j.realm.Pac4jRealm;
import io.buji.pac4j.subject.Pac4jPrincipal;
import io.buji.pac4j.token.Pac4jToken;
import lombok.extern.log4j.Log4j;

/**
 * @program emcp-portal
 * @ClassName EmcpRealm
 * @description: 自定义 认证和授权
 * @author: sky
 * @create: 2019/04/28 09:40
 */
@Log4j
public class EmcpRealm extends Pac4jRealm {

    @Autowired(required = false)
    private final List<AuthenticateListener> listeners = new ArrayList<>();

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    public EmcpRealm() {
        super();
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken authenticationToken)
        throws AuthenticationException {

        final Pac4jToken token = (Pac4jToken)authenticationToken;
        final List<CommonProfile> profiles = token.getProfiles();
        CommonProfile profile = profiles.get(0);
        log.info("profile:" + profile);
        listeners.forEach(listener -> listener.onAuthenticate(profile));
        final Pac4jPrincipal principal = new Pac4jPrincipal(profiles, this.getPrincipalNameAttribute());
        final PrincipalCollection principalCollection = new SimplePrincipalCollection(principal, getName());
        return new SimpleAuthenticationInfo(principalCollection, profiles.hashCode());
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(final PrincipalCollection principals) {
        final Set<String> roles = new HashSet<>();
        final Set<String> permissions = new HashSet<>();
        final Pac4jPrincipal principal = principals.oneByType(Pac4jPrincipal.class);
        if (principal != null) {
            final List<CommonProfile> profiles = principal.getProfiles();
            for (CommonProfile profile : profiles) {
                if (profile != null) {
                    roles.addAll(profile.getRoles());
                    permissions.addAll(profile.getPermissions());
                }
            }
        }
        final SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRoles(roles);
        simpleAuthorizationInfo.addStringPermissions(permissions);
        eventPublisher.publishEvent(new AuthorizeAfterEvent(simpleAuthorizationInfo));
        return simpleAuthorizationInfo;
    }

}
